#if 0x0
#include "nam.h"
////#include "private/qnoncontiguousbytedevice_p.h"

T_NetworkAccessManager::T_NetworkAccessManager(QObject *parent)
    : QNetworkAccessManager(parent)
{
}

void T_NetworkAccessManager::appendBackendFactory(T_NetworkAccessBackendFactory *a_factory)
{
    T_WRITE_LOCKER(v_lock, &f_factory_list_lock);
    f_factory_list.append(a_factory);
}

void T_NetworkAccessManager::prependBackendFactory(T_NetworkAccessBackendFactory *a_factory)
{
    T_WRITE_LOCKER(v_lock, &f_factory_list_lock);
    f_factory_list.prepend(a_factory);
}

void T_NetworkAccessManager::addToSilentList(QRegExp a_rx)
{
    T_WRITE_LOCKER(v_lock, &f_factory_list_lock);
    f_silent_list.append(a_rx);
}

QNetworkReply *T_NetworkAccessManager::createRequest(
        Operation op,
        const QNetworkRequest & request,
        QIODevice * outgoingData)
{
    bool v_silent = false;
    QString v_url_str = QString::fromUtf8(request.url().toEncoded());
    foreach(QRegExp v_rx, f_silent_list)
    {
        if(v_rx.indexIn(v_url_str) != -1)
        {
            v_silent = true;
            break;
        }
    }
    if(!v_silent)
    {
        qDebug() << "[NetworkAccessManager::createRequest()]" << request.url();
    }
    QObject *v_backend = this->createBackend(op, request, outgoingData);
    if(!v_backend)
    {
        T_READ_LOCKER(v_lock, &f_factory_list_lock);
        foreach(T_NetworkAccessBackendFactory *v_factory, f_factory_list)
        {
            v_backend = v_factory->create(this, op, request, outgoingData);
            if(v_backend) break;
        }
    }
    return QNetworkAccessManager::createRequestWithBackend(op, request, outgoingData, v_backend);
}

QNetworkReply *T_NetworkAccessManager::createRequestWithBackend(
        Operation op,
        const QNetworkRequest &request,
        QIODevice *outgoingData,
        QObject *backend)
{
    qDebug() << "[NetworkAccessManager::createRequestWithBackend()]" << request.url();
    if(request.hasRawHeader("Range"))
    {
        qDebug() << "[NetworkAccessManager::createRequestWithBackend()]" << request.url() << request.rawHeader("Range");
    }
    else
    {
        qDebug() << "[NetworkAccessManager::createRequestWithBackend()]" << request.url();
    }
    return QNetworkAccessManager::createRequestWithBackend(op, request, outgoingData, backend);
}

static QNetworkReply::NetworkError s_networkErrorCodeFromHttpStatus(int httpStatusCode, const QUrl &url);

T_HttpAccessBackend::T_HttpAccessBackend(T_NetworkAccessManager * nam)
    : QNetworkAccessBackend()
    , f_nam(nam)
    , f_httpReply(0)
    , f_uploadDevice(0)
#ifndef QT_NO_OPENSSL
    , f_pendingSslConfiguration(0), f_pendingIgnoreAllSslErrors(false)
#endif
{
    //QNetworkAccessManagerPrivate *QNetworkAccessBackend::manager;
    this->manager = nam->d_func();
}

T_HttpAccessBackend::~T_HttpAccessBackend()
{
    p_disconnectFromHttp();
#ifndef QT_NO_OPENSSL
    delete f_pendingSslConfiguration;
#endif
}

T_NetworkAccessManager *T_HttpAccessBackend::networkAccessManager()
{
    return f_nam;
}

QIODevice *T_HttpAccessBackend::uploadDevice()
{
    if(f_uploadDevice)
    {
        return f_uploadDevice;
    }
    if(reply->outgoingData || reply->outgoingDataBuffer)
    {
        f_uploadDevice = QNonContiguousByteDeviceFactory::wrap(createUploadByteDevice());
        f_uploadDevice->setParent(this);
    }
    else
    {
        f_uploadDevice = 0;
    }
    return f_uploadDevice;
}

void T_HttpAccessBackend::setUploadDevice(QIODevice *a_device)
{
    f_uploadDevice = a_device;
}

/* virtual */ void T_HttpAccessBackend::open()
{
    f_httpReply = this->createHttpReply();
    /////if((void *)this!=(void *)f_httpReply) f_httpReply->setParent(this);
    /////QObject *v_replyObj = (QObject *)f_httpReply;
    QObject *v_replyObj = dynamic_cast<QObject *>(f_httpReply);
    if((void *)this!=(void *)v_replyObj) v_replyObj->setParent(this);
#ifndef QT_NO_OPENSSL
    if (f_pendingSslConfiguration)
        f_httpReply->setSslConfiguration(*f_pendingSslConfiguration);
    if (f_pendingIgnoreAllSslErrors)
        f_httpReply->ignoreSslErrors();
    f_httpReply->ignoreSslErrors(f_pendingIgnoreSslErrorsList);
#endif
    //authenticationRequired()
    connect(v_replyObj,
            SIGNAL(impl_authenticationRequired(QAuthenticator*)),
            SLOT(replyAuthenticationRequired(QAuthenticator*)));
    //metaDataChanged()
    connect(v_replyObj, SIGNAL(impl_metaDataChanged()), SLOT(replyMetaDataChanged()));
    //readyRead()
    connect(v_replyObj, SIGNAL(impl_readyRead()), SLOT(replyReadyRead()));
    //finished()
    connect(v_replyObj, SIGNAL(impl_finished()), SLOT(replyFinished()));
    //error()
    connect(v_replyObj, SIGNAL(impl_error(QNetworkReply::NetworkError)),
            SLOT(replyError(QNetworkReply::NetworkError)));
    //uploadProgress()
    connect(v_replyObj, SIGNAL(impl_uploadProgress(qint64,qint64)), SLOT(replyUploadProgress(qint64,qint64)));
#ifndef QT_NO_OPENSSL
    connect(v_replyObj, SIGNAL(impl_sslErrors(QList<QSslError>)), SLOT(sslErrors(QList<QSslError>)));
#endif
    f_httpReply->start(
            this->networkAccessManager(),
            this->operation(),
            this->request(),
            this->uploadDevice()
            );
}

/* virtual */ void T_HttpAccessBackend::downstreamReadyWrite()
{
    //qDebug() << "[HttpAccessBackend::downstreamReadyWrite()]";
    p_readFromHttp();
}

/* virtual */ void T_HttpAccessBackend::copyFinished(QIODevice *dev)
{
    //TODO: delete this function if possible
    delete dev;
    T_HttpAccessBackend::finished();
}
/* slot */ void T_HttpAccessBackend::finished()
{
    //qDebug() << "[HttpAccessBackend::finished()]" << QNetworkAccessBackend::request().url();
    p_disconnectFromHttp();
    QNetworkAccessBackend::finished();
}

/* slot */ void T_HttpAccessBackend::replyReadyRead()
{
    //qDebug() << "HttpAccessBackend::replyReadyRead()";
    p_readFromHttp();
}

/* slot */ void T_HttpAccessBackend::replyFinished()
{
    //TODO: delete this line(?)
    // we haven't read everything yet. Wait some more.
#if 0x0
    if (m_httpReply->bytesAvailable()) return;
#else
    if (f_httpReply->bytesAvailable())
    {
        QByteDataBuffer list;
        QByteArray v_bytes = f_httpReply->read(f_httpReply->bytesAvailable());//FIXME readAll()
        list.append(v_bytes);
        //if (!list.isEmpty())
        QNetworkAccessBackend::writeDownstreamData(list);
    }
#endif

    int statusCode = f_httpReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if (statusCode >= 400) {
        // it's an error reply
        QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply",
                                                      "Error downloading %1 - server replied: %2"));
        msg = msg.arg(url().toString(), f_httpReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
        QNetworkAccessBackend::error(
                s_networkErrorCodeFromHttpStatus(statusCode, url()),
                msg);
    }
    T_HttpAccessBackend::finished();
}

/* slot */ void T_HttpAccessBackend::replyMetaDataChanged()
{
    //qDebug() << "HttpAccessBackend::replyMetaDataChanged():" << QNetworkAccessBackend::request().url();
    // HTTP Status
    QNetworkAccessBackend::setAttribute(
            QNetworkRequest::HttpStatusCodeAttribute,
            f_httpReply->attribute(QNetworkRequest::HttpStatusCodeAttribute));
    // HTTP Reason Phrase
    QNetworkAccessBackend::setAttribute(
            QNetworkRequest::HttpReasonPhraseAttribute,
            f_httpReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute));

    // HTTP Response Headers
    QList<QByteArray> v_headerList = f_httpReply->rawHeaderList();
    foreach(QByteArray v_first, v_headerList)
    {
        QByteArray v_second = f_httpReply->rawHeader(v_first);
        //qDebug() << v_first << v_second;
        QNetworkAccessBackend::setRawHeader(v_first, v_second);
    }
    // is it a redirection?
    const int statusCode = f_httpReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    p_checkForRedirect(statusCode);
    QNetworkAccessBackend::metaDataChanged();
}

/* slot */ void T_HttpAccessBackend::namAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
{
    Q_UNUSED(reply);
    QNetworkAccessBackend::authenticationRequired(authenticator);
}

/* slot */ void T_HttpAccessBackend::replyAuthenticationRequired(QAuthenticator *authenticator)
{
    //qDebug() << "[HttpAccessBackend::replyAuthenticationRequired()]" << authenticator->realm();
    QNetworkAccessBackend::authenticationRequired(authenticator);
}

/* slot */ void T_HttpAccessBackend::replyError(QNetworkReply::NetworkError errorCode)
{
    T_HttpAccessReply *v_reply = dynamic_cast<T_HttpAccessReply *>(QObject::sender());
    QString errorString = v_reply ? v_reply->errorString() : QString::number(errorCode);
    //qDebug() << "[HttpAccessBackend::replyError()]" << errorCode << errorString;
    QNetworkAccessBackend::error(errorCode, errorString);
    T_HttpAccessBackend::finished();
}

/* slot */ void T_HttpAccessBackend::replyUploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
    //qDebug() << "[HttpAccessBackend::replyUploadProgress()]" << bytesSent << bytesTotal;
    QNetworkAccessBackend::emitReplyUploadProgress(bytesSent, bytesTotal);
}

/* slot */ void T_HttpAccessBackend::replyDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
    //TODO: delete this
    //qDebug() << "[HttpAccessBackend::replyDownloadProgress()]" << bytesReceived << bytesTotal;
}

//TODO: delete m_pending...
void T_HttpAccessBackend::ignoreSslErrors()
{
    if (f_httpReply)
        f_httpReply->ignoreSslErrors();
    else
        f_pendingIgnoreAllSslErrors = true;
}

void T_HttpAccessBackend::ignoreSslErrors(const QList<QSslError> &errors)
{
    if (f_httpReply)
    {
        f_httpReply->ignoreSslErrors(errors);
    }
    else
    {
        // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
        // is called before QNetworkAccessManager::get() (or post(), etc.)
        f_pendingIgnoreSslErrorsList = errors;
    }
}

void T_HttpAccessBackend::fetchSslConfiguration(QSslConfiguration & config) const
{
    if (f_httpReply)
        config = f_httpReply->sslConfiguration();
    else if (f_pendingSslConfiguration)
        config = *f_pendingSslConfiguration;
}

void T_HttpAccessBackend::setSslConfiguration(const QSslConfiguration & config)
{
    if (f_httpReply)
        f_httpReply->setSslConfiguration(config);
    else if (f_pendingSslConfiguration)
        *f_pendingSslConfiguration = config;
    else
        f_pendingSslConfiguration = new QSslConfiguration(config);
}

void T_HttpAccessBackend::p_disconnectFromHttp()
{
}

void T_HttpAccessBackend::p_readFromHttp()
{
    QByteDataBuffer list;
    while (f_httpReply->bytesAvailable() != 0
           && QNetworkAccessBackend::nextDownstreamBlockSize() != 0
           && QNetworkAccessBackend::nextDownstreamBlockSize() > list.byteAmount()) {
        QByteArray v_bytes = f_httpReply->read(QNetworkAccessBackend::nextDownstreamBlockSize() - list.byteAmount());
        list.append(v_bytes);
    }
    if (!list.isEmpty()) QNetworkAccessBackend::writeDownstreamData(list);
}

void T_HttpAccessBackend::p_checkForRedirect(const int statusCode)
{
    switch (statusCode) {
    case 301:				   // Moved Permanently
    case 302:				   // Found
    case 303:				   // See Other
    case 307:				   // Temporary Redirect
        // What do we do about the caching of the HTML note?
        // The response to a 303 MUST NOT be cached, while the response to
        // all of the others is cacheable if the headers indicate it to be
        QByteArray header = QNetworkAccessBackend::rawHeader("location");
        QUrl url = QUrl::fromEncoded(header);
        if (!url.isValid()) url = QUrl(QLatin1String(header));
        ////p_checkForRedirect_YouTube(url); //TODO: move to T_HttpReply
        QNetworkAccessBackend::redirectionRequested(url);
    }
}

static QNetworkReply::NetworkError s_networkErrorCodeFromHttpStatus(int httpStatusCode, const QUrl &url)
{
    QNetworkReply::NetworkError code;
    // we've got an error
    switch (httpStatusCode) {
    case 401:			   // Authorization required
        code = QNetworkReply::AuthenticationRequiredError;
        break;

    case 403:			   // Access denied
        code = QNetworkReply::ContentOperationNotPermittedError;
        break;

    case 404:			   // Not Found
        code = QNetworkReply::ContentNotFoundError;
        break;

    case 405:			   // Method Not Allowed
        code = QNetworkReply::ContentOperationNotPermittedError;
        break;

    case 407:
        code = QNetworkReply::ProxyAuthenticationRequiredError;
        break;

    default:
        if (httpStatusCode > 500) {
            // some kind of server error
            code = QNetworkReply::ProtocolUnknownError;
        } else if (httpStatusCode >= 400) {
            // content error we did not handle above
            code = QNetworkReply::UnknownContentError;
        } else {
            qWarning("QNetworkAccess: got HTTP status code %d which is not expected from url: \"%s\"",
                     httpStatusCode, qPrintable(url.toString()));
            code = QNetworkReply::ProtocolFailure;
        }
    }

    return code;
}

T_HttpAccessReply_QNetworkReply::T_HttpAccessReply_QNetworkReply(
        T_HttpAccessBackend *parent, QNetworkReply *a_reply)
    : T_HttpAccessReply(parent)
{
    m_netReply = a_reply;
    if(!m_netReply)
    {
        m_netReply = backend()->networkAccessManager()->createRequestWithBackend(
                backend()->operation(),
                backend()->request(),
                backend()->uploadDevice(),
                0
                );
    }
    // connect
    p_connectQNetworkReply(m_netReply);
}

T_HttpAccessReply_QNetworkReply::~T_HttpAccessReply_QNetworkReply()
{
    m_netReply->deleteLater();
}

// raw headers:
/* virtual */ bool T_HttpAccessReply_QNetworkReply::hasRawHeader(const QByteArray &headerName) const
{
    return m_netReply->hasRawHeader(headerName);
}
/* virtual */ QList<QByteArray> T_HttpAccessReply_QNetworkReply::rawHeaderList() const
{
    return m_netReply->rawHeaderList();
}
/* virtual */ QByteArray T_HttpAccessReply_QNetworkReply::rawHeader(const QByteArray &headerName) const
{
    return m_netReply->rawHeader(headerName);
}

// attributes
/* virtual */ QVariant T_HttpAccessReply_QNetworkReply::attribute(QNetworkRequest::Attribute code) const
{
    return m_netReply->attribute(code);
}

// reading
/* virtual */ qint64 T_HttpAccessReply_QNetworkReply::bytesAvailable()
{
    return m_netReply->bytesAvailable();
}
/* virtual */ QByteArray T_HttpAccessReply_QNetworkReply::read(qint64 a_max)
{
    return m_netReply->read(a_max);
}

// errorString()
/* virtual */ QString T_HttpAccessReply_QNetworkReply::errorString() const
{
    if(m_netReply) return m_netReply->errorString();
    return "";
}

// SSL
/* virtual */ void T_HttpAccessReply_QNetworkReply::ignoreSslErrors()
{
    if(m_netReply) m_netReply->ignoreSslErrors();
}
/* virtual */ void T_HttpAccessReply_QNetworkReply::ignoreSslErrors(const QList<QSslError> & errors)
{
    if(m_netReply) m_netReply->ignoreSslErrors(errors);
}
/* virtual */ QSslConfiguration T_HttpAccessReply_QNetworkReply::sslConfiguration() const
{
    if(m_netReply) return m_netReply->sslConfiguration();
    return QSslConfiguration::defaultConfiguration();
}
/* virtual */ void T_HttpAccessReply_QNetworkReply::setSslConfiguration(const QSslConfiguration & config)
{
    if(m_netReply) m_netReply->setSslConfiguration(config);
}
#endif // 0
